package com.ruoyi.common.net.mqtt.multi;

import com.ruoyi.common.net.mqtt.IMessageHandler;
import com.ruoyi.common.utils.bean.Factory;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author xumh
 * @title: MqttClientManager
 * @description: TODO
 * @date 2024/12/1815:03
 */
public class MqttClientManager {
    private final String __random_id__ = (new Date()).getTime() + "";
    @Autowired(
            required = false
    )
    private MqttClientManager.MqttProperties properties;
    @Autowired(
            required = false
    )
    private List<IMessageHandler> messageHandlers;
    public static ConcurrentHashMap<String, MqttClientConnect> mqttClients = new ConcurrentHashMap();

    public MqttClientManager() {
    }

    public static MqttClientManager instance() {
        return (MqttClientManager) Factory.instance(MqttClientManager.class);
    }

    public MqttClientConnect defaultMqttClient() throws Exception {
        if (this.properties == null) {
            return null;
        } else {
            MqttClientManager.MqttConnectOption option = this.properties.getClient();
            if (option != null) {
                String clientId = option.getId() + "-" + this.__random_id__;
                if (mqttClients.contains(clientId)) {
                    return (MqttClientConnect)mqttClients.get(clientId);
                } else {
                    MqttClientConnect mqttClientConnect = new MqttClientConnect();
                    mqttClientConnect.setMqttClientId(clientId);
                    mqttClientConnect.setMqttClient(option.getHost(), clientId, option.getUsername(), option.getPassword(), true, new MqttClientCallback(option.getId(), this.messageHandlers));
                    mqttClients.put(option.getId(), mqttClientConnect);
                    return mqttClientConnect;
                }
            } else {
                return null;
            }
        }
    }

    public MqttClientConnect createMqttClient(String clientId, String host, String user, String password, boolean cleanSession) throws Exception {
        MqttClientConnect mqttClientConnect = new MqttClientConnect();
        mqttClientConnect.setMqttClientId(clientId);
        mqttClientConnect.setMqttClient(host, clientId, user, password, cleanSession, new MqttClientCallback(clientId, this.messageHandlers));
        mqttClients.put(clientId, mqttClientConnect);
        return mqttClientConnect;
    }

    public MqttClientConnect createMqttClient(String clientId) throws Exception {
        if (this.properties == null) {
            return null;
        } else {
            MqttClientManager.MqttConnectOption option = this.properties.getClient();
            if (option == null) {
                return null;
            } else {
                if (clientId == null || "".equals(clientId.trim())) {
                    clientId = option.getId();
                }

                if (mqttClients.contains(clientId)) {
                    return (MqttClientConnect)mqttClients.get(clientId);
                } else {
                    MqttClientConnect mqttClientConnect = new MqttClientConnect();
                    mqttClientConnect.setMqttClientId(clientId);
                    mqttClientConnect.setMqttClient(option.getHost(), clientId, option.getUsername(), option.getPassword(), true, new MqttClientCallback(clientId, this.messageHandlers));
                    mqttClients.put(clientId, mqttClientConnect);
                    return mqttClientConnect;
                }
            }
        }
    }

    public void subscribe(String clientId, String topic) {
        try {
            MqttClientConnect mqttClientConnect = (MqttClientConnect)mqttClients.get(clientId);
            mqttClientConnect.subscribe(StringUtils.commaDelimitedListToStringArray(topic));
        } catch (MqttException var4) {
            var4.printStackTrace();
        }

    }

    public void subscribe(String clientId, String[] topics) {
        try {
            MqttClientConnect mqttClientConnect = (MqttClientConnect)mqttClients.get(clientId);
            mqttClientConnect.subscribe(topics);
        } catch (MqttException var4) {
            var4.printStackTrace();
        }

    }

    public void unsubscribe(String clientId, String topic) {
        try {
            MqttClientConnect mqttClientConnect = (MqttClientConnect)mqttClients.get(clientId);
            mqttClientConnect.unsubscribe(topic);
        } catch (MqttException var4) {
            var4.printStackTrace();
        }

    }

    public void subscribe(String[] topics) {
        try {
            MqttClientConnect mqttClientConnect = this.defaultMqttClient();
            if (mqttClientConnect == null) {
                return;
            }

            mqttClientConnect.subscribe(topics);
        } catch (Exception var3) {
            var3.printStackTrace();
        }

    }

    public void unsubscribe(String topic) {
        try {
            MqttClientConnect mqttClientConnect = this.defaultMqttClient();
            if (mqttClientConnect == null) {
                return;
            }

            mqttClientConnect.unsubscribe(topic);
        } catch (Exception var3) {
            var3.printStackTrace();
        }

    }

    public void publish(String clientId, String topic, String message) {
        try {
            MqttClientConnect mqttClientConnect = (MqttClientConnect)mqttClients.get(clientId);
            mqttClientConnect.publish(topic, message);
        } catch (MqttException var5) {
            var5.printStackTrace();
        }

    }

    public void publish(String clientId, String topic, byte[] payload) {
        try {
            MqttClientConnect mqttClientConnect = (MqttClientConnect)mqttClients.get(clientId);
            mqttClientConnect.publish(topic, payload, 0, false);
        } catch (MqttException var5) {
            var5.printStackTrace();
        }

    }

    public void publish(String clientId, String topic, byte[] payload, int qos, boolean retained) {
        try {
            MqttClientConnect mqttClientConnect = (MqttClientConnect)mqttClients.get(clientId);
            mqttClientConnect.publish(topic, payload, qos, retained);
        } catch (MqttException var7) {
            var7.printStackTrace();
        }

    }

    public void publish(String topic, String message) {
        try {
            MqttClientConnect mqttClientConnect = this.defaultMqttClient();
            if (mqttClientConnect == null) {
                return;
            }

            mqttClientConnect.publish(topic, message);
        } catch (MqttException var4) {
            var4.printStackTrace();
        } catch (Exception var5) {
            throw new RuntimeException(var5);
        }

    }

    public void publish(String topic, byte[] payload) {
        try {
            MqttClientConnect mqttClientConnect = this.defaultMqttClient();
            if (mqttClientConnect == null) {
                return;
            }

            mqttClientConnect.publish(topic, payload, 0, false);
        } catch (MqttException var4) {
            var4.printStackTrace();
        } catch (Exception var5) {
            throw new RuntimeException(var5);
        }

    }

    public void publish(String topic, byte[] payload, int qos, boolean retained) {
        try {
            MqttClientConnect mqttClientConnect = this.defaultMqttClient();
            if (mqttClientConnect == null) {
                return;
            }

            mqttClientConnect.publish(topic, payload, qos, retained);
        } catch (MqttException var6) {
            var6.printStackTrace();
        } catch (Exception var7) {
            throw new RuntimeException(var7);
        }

    }

    public static ConcurrentHashMap<String, MqttClientConnect> clients() {
        return mqttClients;
    }

    @Component
    @ConfigurationProperties(
            prefix = "mqtt",
            ignoreUnknownFields = false,
            ignoreInvalidFields = false
    )
    public static class MqttProperties {
        private Boolean enable = false;
        private MqttClientManager.MqttConnectOption client = new MqttClientManager.MqttConnectOption();
        private List<Map<String, String>> clients = new ArrayList();

        public MqttProperties() {
        }

        public Boolean getEnable() {
            return this.enable;
        }

        public void setEnable(Boolean enable) {
            this.enable = enable;
        }

        public MqttClientManager.MqttConnectOption getClient() {
            return this.client;
        }

        public void setClient(MqttClientManager.MqttConnectOption client) {
            this.client = client;
        }

        public List<Map<String, String>> getClients() {
            return this.clients;
        }

        public void setClients(List<Map<String, String>> clients) {
            this.clients = clients;
        }
    }

    public static class MqttConnectOption {
        private String id;
        private String username;
        private String password;
        private String host;
        private String wsuri;
        private int completionTimeout;

        public MqttConnectOption() {
        }

        public String getId() {
            return this.id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getUsername() {
            return this.username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return this.password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public String getHost() {
            return this.host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public String getWsuri() {
            return this.wsuri;
        }

        public void setWsuri(String wsuri) {
            this.wsuri = wsuri;
        }

        public int getCompletionTimeout() {
            return this.completionTimeout;
        }

        public void setCompletionTimeout(int completionTimeout) {
            this.completionTimeout = completionTimeout;
        }
    }
}
